package com.woniu.woniu_bx.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniu.woniu_bx.filter.AuthUser;
import com.woniu.woniu_bx.filter.AuthticationFilter;
import com.woniu.woniu_bx.filter.JwtVarifyFilter;
import com.woniu.woniu_bx.filter.JwtVarifyProvider;
import com.woniu.woniu_bx.pojo.ResponseEntity;
import com.woniu.woniu_bx.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @Description spring-Security权限控制
 * @Author leonie
 * @Date 2022/8/27 11:53
 */
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private DaoAuthenticationProvider daoAuthenticationProvider;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(apiAuthticationFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterAfter(jwtVarifyFilter(), AuthticationFilter.class);
        http.antMatcher("/admin/**")  //指定以/api/开头的请求使用以下配置
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS).permitAll() //请求方法OPTIONS放行
                .antMatchers("/admin/login","/admin/allMenus").permitAll()
                .anyRequest().authenticated()
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().csrf().disable();
    }

    public AuthticationFilter apiAuthticationFilter() throws Exception {
        //构造方法的参数是一个URL，只有该URL的请求才回进入该过滤器
        AuthticationFilter apiAuthticationFilter = new AuthticationFilter("/admin/login");

        apiAuthticationFilter.setAuthenticationManager(authenticationManager());

        //认证成功的回调
        apiAuthticationFilter.setAuthenticationSuccessHandler((req, resp, authtication) -> {

            Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            resp.setContentType("application/json;charset=UTF-8");
            AuthUser user = (AuthUser)obj;
            //将user返回，调用成功的操作
            String r = new ObjectMapper().writeValueAsString(ResponseEntity.SUCCESS("登录成功",user));
            resp.getWriter().write(r);
            log.debug("user{}",user);
            String token = jwtUtil.createJWT(user.getId(), user.getUsername());
            resp.addHeader("token",token);
            resp.getWriter().close();
        });

        return apiAuthticationFilter;
    }

    public JwtVarifyFilter jwtVarifyFilter() throws Exception {
        //构造方法的参数是一个URL，只有该URL的请求才回进入该过滤器
        JwtVarifyFilter jwtVarifyFilter = new JwtVarifyFilter("/api/v1/**");

        jwtVarifyFilter.setAuthenticationManager(authenticationManager());

        jwtVarifyFilter.setAuthenticationFailureHandler((req,resp,authtication)->{
            String r = new ObjectMapper().writeValueAsString(ResponseEntity.FAIL("500","token无效"));
            resp.getWriter().write(r);
            resp.getWriter().close();
        });

        return jwtVarifyFilter;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(daoAuthenticationProvider).authenticationProvider(jwtVerifyProvider());
    }

    @Bean
    public JwtVarifyProvider jwtVerifyProvider() {
        return new JwtVarifyProvider();
    }
}
